// 空基类详解
// 什么是空基类？
// 空基类是不包含任何非静态数据成员、虚函数表指针或其他需要存储空间的成员的类。
// 典型的空基类可能包含：
class EmptyClass
{
public:
    void someFunction() {}       // 非虚函数不占用对象空间
    static int someStaticMember; // 静态成员不占用对象空间
    typedef int value_type;      // 类型定义不占用对象空间

    // 没有非静态数据成员
    // 没有虚函数（否则会有虚函数表指针）
};
// 空基类的大小
// 在C++中，即使是空类也必须有非零大小，这是为了确保同类型的不同对象有不同的内存地址：
// 因此，空类通常占用1字节的内存：

// 空基类优化（EBO）
// 空基类优化是一种编译器优化技术，允许派生类不为空基类分配额外的存储空间。这种优化仅适用于继承关系，不适用于成员变量：
// 使用复合
class WithMember
{
    EmptyClass e; // 通常占用至少1字节
    int data;     // 4字节
}; // 通常大小为8字节（考虑对齐）

// 使用继承
class WithInheritance : private EmptyClass
{
    int data; // 4字节
}; // 通常大小为4字节（应用EBO）
// 为什么EBO只适用于继承？
// 这是因为C++标准要求不同的对象必须有不同的地址，但允许基类子对象与派生类对象共享地址。
// 当使用继承时，派生类对象和其基类子对象可以共享相同的起始地址，而成员变量必须有自己的地址。

// 空类的实际应用
// 1. 策略模式和特性类（Policy and Traits Classes）
// 空的特性类，提供类型信息
template <typename T>
struct NumericTraits
{
};

// 特化为int
template <>
struct NumericTraits<int>
{
    static constexpr bool is_signed = true;
    static constexpr int min_value = INT_MIN;
    static constexpr int max_value = INT_MAX;
};

// 使用特性类的算法
template <typename T>
class NumericAlgorithms : private NumericTraits<T>
{
    // 使用NumericTraits<T>提供的类型信息
    T data[100];
};

// 2. Mixin类和行为注入
// 提供比较操作的Mixin
template <typename T>
class Comparable
{
public:
    bool operator>(const T &other) const
    {
        return static_cast<const T &>(*this) != other &&
               !(static_cast<const T &>(*this) < other);
    }

    bool operator<=(const T &other) const
    {
        return !(*this > other);
    }

    bool operator>=(const T &other) const
    {
        return !(*this < other);
    }
};

// 使用Mixin的类只需实现<和==
class Integer : private Comparable<Integer>
{
    int value;

public:
    // 使基类的操作符在派生类中可见
    using Comparable<Integer>::operator>;
    using Comparable<Integer>::operator<=;
    using Comparable<Integer>::operator>=;

    bool operator<(const Integer &other) const
    {
        return value < other.value;
    }

    bool operator==(const Integer &other) const
    {
        return value == other.value;
    }
};

// 3. 标签分派
// 标签类
struct FastAlgorithmTag
{
};
struct AccurateAlgorithmTag
{
};

// 根据标签选择算法
template <typename Tag>
class MathFunctions
{
protected:
    static double sin_impl(double x, FastAlgorithmTag)
    {
        // 快速但近似的实现
        return x - x * x * x / 6.0; // 泰勒级数的前几项
    }

    static double sin_impl(double x, AccurateAlgorithmTag)
    {
        // 精确但较慢的实现
        return std::sin(x);
    }
};

// 快速版本
class FastMath : private MathFunctions<FastAlgorithmTag>,
                 private FastAlgorithmTag
{
public:
    static double sin(double x)
    {
        return sin_impl(x, FastAlgorithmTag());
    }
};
// 多重继承中的EBO
// EBO在多重继承中尤其有用：
template <typename T1, typename T2, typename T3>
class Tuple : private T1, private T2, private T3
{
    // 如果T1, T2, T3都是空类，Tuple不会为它们分配额外空间
};
// 总结
// 空基类是C++中强大的设计工具，特别是在模板编程和策略设计中。通过私有继承和空基类优化，我们可以：
// 1.在不增加对象大小的情况下注入行为
// 2.利用策略模式和特性类提供编译时信息
// 3.实现标签分派和其他高级元编程技术
// 4.创建更内存高效的复合对象
// 这就是为什么条款39将空基类优化列为私有继承的一个合理用例，尽管在大多数其他情况下，复合是表达"is-implemented-in-terms-of"关系的更好选择。